﻿/*
Copyright 2010 Matías Fidemraizer (www.matiasfidemraizer.com).

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
*/

using System;
using System.Collections.Generic;
using System.Linq;
using Comkarl.Architecture.Patterns.DomainModel;

namespace Comkarl.Architecture.Patterns.UnitOfWork
{
    /// <summary>
    /// Represents a repository of work objects for an unit of work.
    /// </summary>
    /// <typeparam name="TDomainObjectIdentifierName">
    /// The type for work and domain objects' identifier name.
    /// </typeparam>
    /// <typeparam name="TDomainObject">
    /// The type for managed domain objects.
    /// </typeparam>
    public sealed class WorkObjectRepository<TDomainObjectIdentifierName, TDomainObject> 
        : Repository<TDomainObjectIdentifierName, WorkObject<TDomainObjectIdentifierName, TDomainObject>>, IDisposable, IEnumerable<WorkObject<TDomainObjectIdentifierName, TDomainObject>>
        where TDomainObjectIdentifierName : IEquatable<TDomainObjectIdentifierName>
        where TDomainObject : DomainObject<TDomainObjectIdentifierName>, ICloneable
    {
        /// <summary>
        /// Default constructor.
        /// </summary>
        public WorkObjectRepository()
            : base(new RepositoryIdentifier<TDomainObjectIdentifierName>(default(TDomainObjectIdentifierName)))
        {
            this.workList = new List<WorkObject<TDomainObjectIdentifierName, TDomainObject>>();
        }

        private readonly IList<WorkObject<TDomainObjectIdentifierName, TDomainObject>> workList;

        /// <summary>
        /// Gets the list of stored works.
        /// </summary>
        private IList<WorkObject<TDomainObjectIdentifierName, TDomainObject>> WorkList
        {
            get
            {
                return workList;
            }
        }

        /// <summary>
        /// Gets the number of stored works by this repository.
        /// </summary>
        public int Count
        {
            get
            {
                return WorkList.Count;
            }
        }

        /// <summary>
        /// Gets a work by its identifier.
        /// </summary>
        /// <param name="id">
        /// The identifier.
        /// </param>
        /// <returns>
        /// The desired work.
        /// </returns>
        public override WorkObject<TDomainObjectIdentifierName, TDomainObject> GetByID(DomainObjectIdentifier<TDomainObjectIdentifierName> id)
        {
            return WorkList.Where<WorkObject<TDomainObjectIdentifierName, TDomainObject>>(workObject => workObject.ID == id).First<WorkObject<TDomainObjectIdentifierName, TDomainObject>>();
        }

        /// <summary>
        /// Adds a new work.
        /// </summary>
        /// <param name="newObject">
        /// The work.
        /// </param>
        public override void Add(WorkObject<TDomainObjectIdentifierName, TDomainObject> newObject)
        {
            WorkList.Add(newObject);
        }

        /// <summary>
        /// Currently not supported.
        /// </summary>
        /// <param name="someObject">
        /// Currently not supported.
        /// </param>
        public override void Update(WorkObject<TDomainObjectIdentifierName, TDomainObject> someObject)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        /// Removes a work from this repository.
        /// </summary>
        /// <param name="someObject">
        /// The reference to the work.
        /// </param>
        public override void Remove(WorkObject<TDomainObjectIdentifierName, TDomainObject> someObject)
        {
            WorkList.Remove(someObject);
        }

        /// <summary>
        /// Clears all works for this repository.
        /// </summary>
        internal void Clear()
        {
            WorkList.Clear();
        }

        #region Miembros de IDisposable

        /// <summary>
        /// Releases resources and ends the life of this repository.
        /// </summary>
        public void Dispose()
        {
            Clear();
        }

        #endregion

        #region Miembros de IEnumerable<WorkObject<Guid,TDomainObject>>

        public IEnumerator<WorkObject<TDomainObjectIdentifierName, TDomainObject>> GetEnumerator()
        {
            return WorkList.GetEnumerator();
        }

        #endregion

        #region Miembros de IEnumerable

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return WorkList.GetEnumerator();
        }

        #endregion
    }
}